package com.iwithlong.service.impl;

import com.iwithlong.enums.IndexType;
import com.iwithlong.service.IndexService;
import com.iwithlong.utils.IndexUtils;
import com.iwithlong.utils.LuceneContext;
import com.iwithlong.vo.ActivityAreaVo;
import com.iwithlong.vo.ActivityVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

/**
 * Write class comments here
 * <p>
 * User: TJM
 * Date: 2017/10/13 14:17
 * version $Id: IndexServiceImpl.java, v 0.1  14:17 Exp $
 */
@Service
@Slf4j
public class IndexServiceImpl implements IndexService {



	private NRTManager nrtManager= LuceneContext.getInstance ().getNrtManager ();

	@Override
	public void addActivityIndex (ActivityVo activityVo) {
		try {
			Document doc= IndexUtils.activity2Doc (activityVo);
			nrtManager.addDocument (doc);
			commitIndex();
		} catch (IOException e) {
			log.error("创建活动索引失败",e);
		}
	}

	@Override
	public void addActivityAreaIndex (ActivityAreaVo activityAreaVo) {
		try {
			Document doc= IndexUtils.activityArea2Doc(activityAreaVo);
			nrtManager.addDocument (doc);

			//查询活动点下的所有活动 并更新活动中 活动点的信息
			BooleanQuery booleanQuery = new BooleanQuery();

			Query activityAreaIdQuery= NumericRangeQuery.newLongRange ("activityAreaId", activityAreaVo.getActivityAreaId (), activityAreaVo.getActivityAreaId (), true, true);
			booleanQuery.add (activityAreaIdQuery, BooleanClause.Occur.MUST);

			//索引类型为活动
			Query queryIndexType = new TermQuery(new Term ("indexType", IndexType.ACTIVITY.getCode ()));
			booleanQuery.add (queryIndexType, BooleanClause.Occur.MUST);

			IndexSearcher searcher = LuceneContext.getInstance ().getSearcher ();
			TopDocs docs = searcher.search (booleanQuery,Integer.MAX_VALUE);

			for (ScoreDoc scoreDoc : docs.scoreDocs) {

				Document document=searcher.doc (scoreDoc.doc);

				ActivityVo activityVo = IndexUtils.doc2Activity (document);


				activityVo.setActivityAreaEnable (activityAreaVo.isEnable ());
				activityVo.setActivityAreaStatus (activityAreaVo.getStatus ());
				activityVo.setLatitude (activityAreaVo.getLatitude ());
				activityVo.setLongitude (activityAreaVo.getLongitude ());

				updateActivityIndex(activityVo);
			}


			commitIndex();
		} catch (IOException e) {
			log.error("创建活动点索引失败");
		}
	}

	@Override
	public void updateActivityIndex (ActivityVo activityVo) {
		try {
			Document doc=IndexUtils.activity2Doc (activityVo);
			nrtManager.updateDocument (new Term ("activityId",activityVo.getActivityId ()+IndexType.ACTIVITY.getCode ()),doc);
			commitIndex();
		} catch (IOException e) {
			log.error("更新索引失败",e);
		}
	}

	@Override
	public void updateActivityAreaIndex (ActivityAreaVo activityAreaVo) {
		try {
			Document doc=IndexUtils.activityArea2Doc (activityAreaVo);
			nrtManager.updateDocument (new Term ("activityAreaId",activityAreaVo.getActivityAreaId ()+IndexType.ACTIVITY_AREA.getCode ()),doc);

			//查询活动点下的所有活动 并更新活动中 活动点的信息
			BooleanQuery booleanQuery = new BooleanQuery();

			Query activityAreaIdQuery= NumericRangeQuery.newLongRange ("activityAreaId", activityAreaVo.getActivityAreaId (), activityAreaVo.getActivityAreaId (), true, true);
			booleanQuery.add (activityAreaIdQuery, BooleanClause.Occur.MUST);

			//索引类型为活动
			Query queryIndexType = new TermQuery(new Term ("indexType", IndexType.ACTIVITY.getCode ()));
			booleanQuery.add (queryIndexType, BooleanClause.Occur.MUST);

			IndexSearcher searcher = LuceneContext.getInstance ().getSearcher ();
			TopDocs docs = searcher.search (booleanQuery,Integer.MAX_VALUE);

			for (ScoreDoc scoreDoc : docs.scoreDocs) {

				Document document=searcher.doc (scoreDoc.doc);

				ActivityVo activityVo = IndexUtils.doc2Activity (document);


				activityVo.setActivityAreaEnable (activityAreaVo.isEnable ());
				activityVo.setActivityAreaStatus (activityAreaVo.getStatus ());
				activityVo.setLatitude (activityAreaVo.getLatitude ());
				activityVo.setLongitude (activityAreaVo.getLongitude ());

				updateActivityIndex(activityVo);
			}

			commitIndex();
		} catch (IOException e) {
			log.error("更新索引失败",e);
		}
	}


	@Override
	public void deleteIndex (String id,String indexType) {
		try {

			IndexSearcher searcher = LuceneContext.getInstance ().getSearcher ();

			if (StringUtils.equals (indexType, IndexType.ACTIVITY.getCode ())){
				Query queryEnabel = new TermQuery (new Term ("activityId",id+indexType));
				TopDocs docs  = searcher.search (queryEnabel,Integer.MAX_VALUE);

				if (docs.scoreDocs.length>0) {
					nrtManager.deleteDocuments (new Term ("activityId",id+indexType));

				}

			}else if (StringUtils.equals (indexType, IndexType.ACTIVITY_AREA.getCode ())){

				Query queryEnabel = new TermQuery (new Term ("activityAreaId",id+indexType));
				TopDocs docs  = searcher.search (queryEnabel,Integer.MAX_VALUE);

				if (docs.scoreDocs.length>0) {
					//修改所有该活动点下的 活动状态

					//查询活动点下的所有活动 并更新活动中 活动点的信息
					BooleanQuery booleanQuery = new BooleanQuery();

					Long activityAreaId=Long.valueOf (id);

					Query activityAreaIdQuery= NumericRangeQuery.newLongRange ("activityAreaId", activityAreaId, activityAreaId, true, true);
					booleanQuery.add (activityAreaIdQuery, BooleanClause.Occur.MUST);

					//索引类型为活动
					Query queryIndexType = new TermQuery(new Term ("indexType", IndexType.ACTIVITY.getCode ()));
					booleanQuery.add (queryIndexType, BooleanClause.Occur.MUST);

					TopDocs activityDocs = searcher.search (booleanQuery,Integer.MAX_VALUE);

					for (ScoreDoc scoreDoc : activityDocs.scoreDocs) {
						Document document=searcher.doc (scoreDoc.doc);
						ActivityVo activityVo = IndexUtils.doc2Activity (document);
						activityVo.setActivityAreaEnable (false);
						updateActivityIndex(activityVo);
					}

					nrtManager.deleteDocuments (new Term ("activityAreaId",id+indexType));
				}
			}
			commitIndex();

		} catch (IOException e) {
			log.error("更新索引失败",e);
		}
	}

	@Override
	public void commitIndex () {
		LuceneContext.getInstance ().commitIndex ();
	}

	@Override
	public void reconstructorIndex (List<ActivityVo> activityVoList, List<ActivityAreaVo> activityAreaVoList) {
		try {
			LuceneContext.getInstance ().getNrtManager ().deleteAll ();
			LuceneContext.getInstance ().commitIndex ();

			for (ActivityVo activityVo : activityVoList) {
				addActivityIndex (activityVo);
			}

			for (ActivityAreaVo activityAreaVo : activityAreaVoList) {
				addActivityAreaIndex (activityAreaVo);
			}





		} catch (IOException e) {
			log.error("更新索引失败",e);
		}
	}

	@Override
	public ActivityAreaVo findActivityAreaById (Long id) {

		IndexSearcher searcher = LuceneContext.getInstance ().getSearcher ();

		try {
			Query query = new TermQuery (new Term ("activityAreaId",id+IndexType.ACTIVITY_AREA.getCode ()));
			TopDocs docs  = searcher.search (query,Integer.MAX_VALUE);

			if (docs.scoreDocs.length>0) {
				ScoreDoc scoreDoc = docs.scoreDocs[ 0 ];
				Document document=searcher.doc (scoreDoc.doc);
				return IndexUtils.doc2ActivityArea (document);
			}

		} catch (IOException e) {
			log.error("获取索引失败",e);
		}

		return null;
	}

	@Override
	public ActivityVo findActivityById (Long id) {

		IndexSearcher searcher = LuceneContext.getInstance ().getSearcher ();

		try {
			Query query = new TermQuery (new Term ("activityId",id+IndexType.ACTIVITY.getCode ()));
			TopDocs docs  = searcher.search (query,Integer.MAX_VALUE);

			if (docs.scoreDocs.length>0) {
				ScoreDoc scoreDoc = docs.scoreDocs[ 0 ];
				Document document=searcher.doc (scoreDoc.doc);
				return IndexUtils.doc2Activity(document);
			}

		} catch (IOException e) {
			log.error("获取索引失败",e);
		}



		return null;
	}


}
